package ie.dit.reg08.attSelector;

import ie.dit.reg08.manager.*;
import java.util.*;

/*
 * Uses a greedy search with no backtracking to construct a distinguishing description
 * Select next property to use based on frequency of attribute use in the corpus
 * Attribute frequency for dev corpus is: type=77, colour=68, size=26, orientation=23, xdimension=16, ydimension=29
 */
public class Incremental1 implements greInterface {
	String id;
	String condition;
	boolean distinguishing;
	Hashtable<String, String> attributeSet;
	Domain domain;
	HashMap<String, Integer> hmAttFreq;
	int totalCount;
	
	public Incremental1(Trial t, HashMap<String, Integer> hm, int total, boolean includetype, boolean enforcedistractorsexcluded) {
		// Attribute position is based on frequency for dev corpus is: type=77, colour=68, size=26, orientation=23, xdimension=16, ydimension=29
		id =  t.getID();	
		condition = t.getCondition();
		domain = t.getDomain();
		distinguishing = false;
		hmAttFreq = hm;
		totalCount = total;
		attributeSet = new Hashtable<String, String>();
		attributeSet = gre(t, includetype, enforcedistractorsexcluded);
	}
	
	public Hashtable<String, String> getDescripton(){
		return attributeSet;
	}
	
	/*
	 * Arg2 = true - type is included even if it does not exclude an distractors
	 * Arg2 = false - type must exclude distractors if it is to be included in the description
	 * Arg3 = true - attribute only included if it excludes a distractor (Arg2 overrides this setting for type)
	 * Arg3 = false - attributes are included even if they do not exclude any distractors
	 */
	public Hashtable<String, String>  gre(Trial t, boolean includetype, boolean enforcedistractorsexcluded) {
		Vector<Entity> vDistractors;
		String sNextProperty = "";
		String sTmp = "";
		Integer max, iTmp;
		Vector<String> vPrevious = new Vector<String>();
		
		Entity target = t.getDomain().getTarget();
		Hashtable<String,String> htTargetAttributes = target.getAttributes();

		
		//iterate through the attribute in the hmAttFreq data structure
		//this ensure that we give each attribute the chance to be selected as 
		//the next property to be included
		Set<String> s = hmAttFreq.keySet();
		Iterator<String> i;
		while (vPrevious.size() < hmAttFreq.size()) {
			
			/*
			 * next property
			 * Find the attribute with the highest frequency
			 * that has not be used so far (i.e. not a member of vPrevious)
			 */
			max = new Integer(0);
			sNextProperty = "";
			i = s.iterator();
			while(i.hasNext()) {
				sTmp = i.next();
				if(!vPrevious.contains(sTmp)) {
					iTmp = hmAttFreq.get(sTmp);
					if(max < iTmp) {
						sNextProperty = sTmp.toString();
						max = new Integer(iTmp.intValue());
					}
				}
			}
			if(!sNextProperty.equals("")) {
				vPrevious.add(sNextProperty);

				/*
				 * check whether it should be added to the description
				 */
				if (htTargetAttributes.containsKey(sNextProperty)) {
					vDistractors = addAttribute(sNextProperty,htTargetAttributes.get(sNextProperty),includetype,enforcedistractorsexcluded);
					/*
					 * check if the description is distinguishing
					 */
					if (vDistractors.isEmpty()) {
						distinguishing = true;
						return attributeSet;
					}
				}
			} else {
				System.err.println("incremental 1: gre sNextProperty not set!");
				System.exit(1);
			}
		}// end while(vPrevious.size(0 < hmAttFreq.size())		
		return attributeSet;
	}
	
	public boolean isDistinguishing() {
		return distinguishing;
	}
	
	/*
	 * Arg3 = true - type is included even if it does not exclude an distractors
	 * Arg3 = false - type must exclude distractors if it is to be included in the description
	 */
	private Vector<Entity> addAttribute(String nextProperty, String value, boolean includetype, boolean enforcedistractorsexcluded) {
		int numdistractors = (domain.distractorSet(attributeSet)).size();
		attributeSet.put(nextProperty, value);
		
		if(enforcedistractorsexcluded) {
			if ((includetype) && (nextProperty.equals("type"))) {
				//if arg3 = true and property = type include it without testing for exclusion of
				//distractors
			} else if (numdistractors > domain.distractorSet(attributeSet).size()) {
				//ok leave the added attribute in the description
			} else {
				attributeSet.remove(nextProperty);
			}
		}
		return domain.distractorSet(attributeSet);
	}
	
	public String getID() {
		return id;
	}
	
	
	/*
	 * Use this xmlDescription for Task 1 standalone
	 */
	/*public String xmlDescription() {  
		  String s = "<TRIAL ID=\"" + id + "\">\n";
		  s = s + "<ATTRIBUTE-SET>\n";
		  
		  Enumeration<String> e = attributeSet.keys();
		  String k;
		  while(e.hasMoreElements()) {
			  k = e.nextElement();
			  s = s + "<ATTRIBUTE NAME=\"" + k + "\" VALUE=\"" + attributeSet.get(k) + "\"/>\n";
		  }
		  s = s + "</ATTRIBUTE-SET>\n";
		  s = s + "</TRIAL>\n";
		  return s;
	}*/

	/*
	 * Use this xmlDescription for Task 3
	 */
	public String xmlDescription() {  
		  String s = "<TRIAL CONDITION=\"" + condition + "\"" +" ID=\"" + id + "\">\n";
		  s = s + domain.getXMLDomainDescription();
		 
		  s = s + "<ATTRIBUTE-SET>\n";
		  Enumeration<String> e = attributeSet.keys();
		  String k;
		  while(e.hasMoreElements()) {
			  k = e.nextElement();
			  s = s + "<ATTRIBUTE NAME=\"" + k + "\" VALUE=\"" + attributeSet.get(k) + "\"/>\n";
		  }
		  s = s + "</ATTRIBUTE-SET>\n";
		  
		  s = s + "</TRIAL>\n";
		  return s;
	}

}
